<?php

declare(strict_types=1);

namespace App\Job;

use App\Model\Product;
use App\Model\User;
use Hyperf\AsyncQueue\Job;
use Hyperf\DbConnection\Db;
use App\Service\SpikeOrderQueueService;
use App\Service\SpikeRollBackQueueService;
use Hyperf\Context\ApplicationContext;

class SpikeBuyExampleJob extends Job
{
	public $params;

	// #[Inject]
	protected SpikeOrderQueueService $spikeOrder;
	protected SpikeRollBackQueueService $spikeRollBack;

	/**
	 * 任务执行失败后的重试次数，即最大执行次数为 $maxAttempts+1 次
	 */
	protected int $maxAttempts = 2;

	public function __construct($params)
	{
		$this->params = $params;
	}

	public function handle()
	{
		$container = ApplicationContext::getContainer();
		$spikeOrder = $container->get(SpikeOrderQueueService::class);
		$spikeRollBack = $container->get(SpikeRollBackQueueService::class);

		$shopData = json_decode($this->params[0], true);
		$orderId = $this->params[1];
		$userid = $this->params[2];

		Db::beginTransaction();
		try {
			$userInfo = User::query()->where('id', $userid)->lockForUpdate()->first();
			if (empty($userInfo)) {
				throw new \Exception('用户不存在');
			}

			$priceAll = 0;  //订单总价格
			$orderGoods = []; //订单的商品数组
			foreach ($shopData as $k => $v) {
				$productInfo = Product::query()->where('id', $v['product_id'])->lockForUpdate()->first();
				if (empty($productInfo)) {
					throw new \Exception('购买失败，商品id为' . $v['product_id'] . '，不存在了');
				}

				if ($productInfo->num < $v['num']) {
					throw new \Exception('购买失败，商品id为' . $v['product_id'] . '，数量不足');
				}

				//orderGood插入一条记录
				$orderGoods[] = [
					'user_id' => $userid,
					'order_id' => $orderId,
					'product_id' => $v['product_id'],
					'product_name' => $productInfo->name,
					'price' => $productInfo->price,
					'num' => $v['num'],
					'created_at' => date('Y-m-d H:i:s'),
					'updated_at' => date('Y-m-d H:i:s'),
				];

				//订单总价格叠加
				$priceAll += $productInfo->price * $v['num'];
			}

			if ($priceAll > $userInfo->balance) {
				throw new \Exception('购买失败，余额不足');
			}

			// 扣除库存
			foreach ($shopData as $k => $v) {
				$res = Product::query()->where('id', $v['product_id'])->where('num', '>=', $v['num'])->lockForUpdate()->decrement('num', $v['num']);
				if (!$res) {
					throw new \Exception('扣减库存失败');
				}
			}

			//扣余额
			$userResult = User::query()->where('id', $userid)->where('balance', '>=', $priceAll)->lockForUpdate()->decrement('balance', $priceAll);
			if (!$userResult) {
				throw new \Exception('扣除余额失败');
			}

			//订单处理
			$spikeOrder->push([$orderGoods, $orderId, $userid, $priceAll]);

			Db::commit();
			return json_encode(['err' => 0, 'msg' => '购买成功']);
		} catch (\Throwable $e) {
			Db::rollBack();
			$spikeRollBack->push($orderId);
			return json_encode(['err' => 1, 'msg' => $e->getMessage()]);
		}
	}
}
